﻿using ICPFrameLib.Business;
using ICPFrameLib.Attributes;
using XHRPMIS.Common;
using EFFC.Frame.Net.Base.Common;
using EFFC.Frame.Net.Base.Data.Base;
using EFFC.Frame.Net.Module.Extend.EWRA.Attributes;
using EFFC.Frame.Net.Module.Extend.EWRA.Attributes.Validation;
using EFFC.Frame.Net.Unit.DB.Parameters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using EFFC.Extends.LinqDLR2SQL;
using EFFC.Frame.Net.Unit.DB;
using EFFC.Frame.Net.Base.Data;
using System.IO;
using EFFC.Frame.Net.Base.Constants;
using System.Text.RegularExpressions;
using ICPFrameLib.Common;
using EFFC.Frame.Net.Unit.DB.Datas;
using System.Text;

namespace XHRPMIS.Business.v1._0
{
     public class MetaDataSet : MyRestLogic
{
    RefExpress ref_express = new RefExpress();
    static object lockobj = new object();

    [EWRARouteDesc("获取下拉框或pop的内容")]
    [EWRARoute("patch", "/metadataset/pop/{id}/{column_name}")]
    [EWRAAddInput("id", "string", "元数据表的uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAAddInput("column_name", "string", "指定栏位的名称", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAAddInput("this_data", "string", @"页面上当前编辑的行资料，先采用url编码，再采用base64编码，原数据格式:
{
    column_name1:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    column_name2:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    .....
    column_nameN:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
}", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAOutputDesc("返回结果", @"如果是授权无效的情况下，返回400错，其它情况的返回结果集（状态为200）如下：{
code:'success-成功，failed-失败',
msg:'提示信息',
column_value:'表示选中值的栏位名称,如果为空，则表示接受UI设定的任意值',
column_show:[{
    column_name:'栏位名称',
    column_desc:'栏位中文名称',
    ui_type:'UI控件类型'
}],
data:[结果集]")]
    object GetPop(string id, string column_name)
    {
        SetCacheEnable(false);
        var metaup = DB.NewMetaUnitParameter();
        var up = DB.NewDBUnitParameter();
        var metainfo = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA_COLUMNS", "a")
                        where t.MetaUID == id && t.MetaColumnName == column_name
                        select new
                        {
                            reference = t.MetaReference
                        }).GetQueryList(metaup);
        if (metainfo.Count <= 0)
        {
            return new
            {
                code = "failed",
                msg = "相关栏位资料不存在，无法继续进行操作"
            };
        }
        var data_type = ComFunc.nvl(metainfo.First().GetValue("data_type"));
        var column_ref = ComFunc.nvl(metainfo.First().GetValue("reference"));
        if (column_ref == "")
        {
            return new
            {
                code = "failed",
                msg = "相关栏位缺少关联数据，无法继续进行操作"
            };
        }

        var refResult = ref_express.ParseExpress(column_ref);
        if (refResult == null)
        {
            return new
            {
                code = "failed",
                msg = "相关栏位关联信息描述存在错误，无法继续进行操作"
            };
        }
        var data_str = ComFunc.nvl(PostDataD.this_data).Replace(" ", "+");
        var this_data_base64str = ComFunc.IsBase64Then(data_str);
        string this_data_str = ComFunc.UrlDecode(this_data_base64str);
        var this_data = FrameDLRObject.IsJsonThen(this_data_str);
        if (data_str != "" && (this_data_str == "" || this_data == null))
        {
            return new
            {
                code = "failed",
                msg = "当前行资料格式不正确"
            };
        }

        var data = new List<FrameDLRObject>();
        UnitDataCollection result = null;
        var dbexpress = refResult.ToDBExpress(this_data, false, null, true);

        if (data_type == "pop"
            || data_type == "multi-pop")
        {
            dbexpress.SetValue("sort_no", true);
            dbexpress.SetValue("$acttype", "QueryByPage");
        }
        result = DB.Excute(up, dbexpress, true);
        data = result.QueryData<FrameDLRObject>();
        //获取column_show的中文名称
        var metacolumns = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
                           join t2 in DB.LamdaTable(metaup, "EXTEND_METADATA_COLUMNS", "b") on t.MetaUID equals t2.MetaUID
                           join t3 in DB.LamdaTable(metaup, "EXTEND_METADATA_DATATYPE", "c").LeftJoin() on t2.MetaDataType equals t3.DataType
                           where t.MetaName == refResult.TableName
                           select new
                           {
                               column_name = t2.MetaColumnName,
                               column_desc = t2.MetaColumnDesc,
                               ui_type = t3.UI_TYPE
                           }).GetQueryList(metaup);
        var dictable = (from t in DB.LamdaTable(metaup, "EXTEND_DICTIONARY_TABLE", "a")
                        where t.DIC_Name == refResult.TableName
                        select new
                        {
                            t.IsTree
                        }
                          ).GetQueryList(metaup);
        if (dictable.Count > 0)
        {
            metacolumns.Add(FrameDLRObject.CreateInstance(@"{
column_name:'code',
column_desc:'编号',
ui_type:'Input'
}"));
            metacolumns.Add(FrameDLRObject.CreateInstance(@"{
column_name:'value',
column_desc:'值',
ui_type:'Input'
}"));
            if (BoolStd.IsNotBoolThen(dictable.First().GetValue("IsTree")))
            {
                metacolumns.Add(FrameDLRObject.CreateInstance(@"{
column_name:'p_code',
column_desc:'父节点编号编号',
ui_type:'Input'
}"));
                metacolumns.Add(FrameDLRObject.CreateInstance(@"{
column_name:'level',
column_desc:'层级',
ui_type:'Input'
}"));
            }
        }
        var column_map = metacolumns.ToDictionary(k => k.GetValue("column_name"), v => new { v.column_desc, v.ui_type });
        if (data_type == "pop"
               || data_type == "multi-pop")
        {
            return new
            {
                code = "success",
                msg = "",
                column_value = refResult.KeyColumn,
                column_show = from t in refResult.ShowColumns
                              select new
                              {
                                  column_name = t,
                                  column_desc = column_map.ContainsKey(t) ? column_map[t].column_desc : "",
                                  ui_type = column_map.ContainsKey(t) ? column_map[t].ui_type : "Input"
                              },
                column_text = refResult.TextColumn,
                total_count = result.TotalRow,
                page = result.CurrentPage,
                total_page = result.TotalPage,
                limit = result.Count_Of_OnePage,
                data
            };
        }
        else
        {
            return new
            {
                code = "success",
                msg = "",
                column_value = refResult.KeyColumn,
                column_show = from t in refResult.ShowColumns
                              select new
                              {
                                  column_name = t,
                                  column_desc = column_map.ContainsKey(t) ? column_map[t].column_desc : "",
                                  ui_type = column_map.ContainsKey(t) ? column_map[t].ui_type : "Input"
                              },
                column_text = refResult.TextColumn,
                data
            };
        }
    }
    [ActionAuth("MetaData")]
    [EWRARouteDesc("获取ui_type为picxy的弹出框内容")]
    [EWRARoute("patch", "/metadataset/pop/picxy/{id}/{column_name}")]
    [EWRAAddInput("id", "string", "元数据表的uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAAddInput("column_name", "string", "指定栏位的名称", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAAddInput("this_data", "string", @"页面上当前编辑的行资料，先采用url编码，再采用base64编码，原数据格式:
{
    column_name1:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    column_name2:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    .....
    column_nameN:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
}", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, true)]
    [EWRAOutputDesc("返回结果", @"如果是授权无效的情况下，返回400错，其它情况的返回结果集（状态为200）如下：{
code:'success-成功，failed-失败',
msg:'提示信息',
filetype:'文件的content-type类型'
filename:'文件名称',
filelength:'文件长度',
file:'文件内容，采用base64加密'
}")]
    object GetPicXYPop(string id, string column_name)
    {
        SetCacheEnable(false);
        var metaup = DB.NewMetaUnitParameter();
        var up = DB.NewDBUnitParameter();
        var s = from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
                where (t.metauid == id || t.metaname == id) && t.IsCreated == 1
                select t;
        var list = s.GetQueryList(metaup);
        if (list.Count <= 0)
        {
            return new
            {
                code = "failed",
                msg = "元数据表不存在",
            };
        }
        dynamic info = list.First();

        var metainfo = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA_COLUMNS", "a")
                        where t.MetaUID == info.MetaUID && t.MetaColumnName == column_name
                        select new
                        {
                            reference = t.MetaReference
                        }).GetQueryList(metaup);
        if (metainfo.Count <= 0)
        {
            return new
            {
                code = "failed",
                msg = "相关栏位资料不存在，无法继续进行操作"
            };
        }
        var column_ref = ComFunc.nvl(metainfo.First().GetValue("reference"));
        if (column_ref == "")
        {
            return new
            {
                code = "failed",
                msg = "相关栏位缺少关联数据，无法继续进行操作"
            };
        }

        var refResult = ref_express.ParseExpress(column_ref);
        if (refResult == null)
        {
            return new
            {
                code = "failed",
                msg = "相关栏位关联信息描述存在错误，无法继续进行操作"
            };
        }
        var data_str = ComFunc.nvl(PostDataD.this_data).Replace(" ", "+");
        var this_data_base64str = ComFunc.IsBase64Then(data_str);
        string this_data_str = ComFunc.UrlDecode(this_data_base64str);
        var this_data = FrameDLRObject.IsJsonThen(this_data_str);
        if (data_str != "" && (this_data_str == "" || this_data == null))
        {
            return new
            {
                code = "failed",
                msg = "当前行资料格式不正确"
            };
        }

        var data = DB.Excute(up, refResult.ToDBExpress(this_data, false, null, true), true);
        if (data.QueryTable.RowLength <= 0)
        {
            return new
            {
                code = "failed",
                msg = "无法查到指定图片数据"
            };
        }
        //只抓取第一行资料的第一个栏位的值
        var result = FileHelper.DoDownLoad(ComFunc.nvl(data.QueryTable[0, 0]));
        return result;
    }
    [EWRARouteDesc("获取主从表级联下拉框的内容，逐级获取")]
    [EWRARoute("post", "/metadataset/cadecase_ms/{id}/{column_name}")]
    [EWRAAddInput("id", "string", "元数据表的uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAAddInput("column_name", "string", "指定栏位的名称", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAAddInput("is_filter_deleted", "bool", "是否过滤掉逻辑删除的资料", "默认为true", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("parent_pk", "string", "上一级资料的PK", "为空时则表示拉出一级列表", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("parent_level", "int", "上一级资料的层级，从0开始", "为空时默认为0，表示拉出一级列表", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("start_meta_name", "string", "起始元数据表名，为空时表示从最顶层开始。比如一种5层结构：小区->片区->楼栋->单元->房屋，期望从楼栋开始选择，则该参数设定为楼栋的表名-Building即可", "默认为空", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, true)]
    [EWRAAddInput("start_level_column", "string", "起始层的栏位名称，parent_pk为空且start_level_column和start_level_value都有值才会生效", "默认为空", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, true)]
    [EWRAAddInput("start_level_value", "string", "起始层的栏位值，多个用逗号分隔，parent_pk为空且start_level_column和start_level_value都有值才会生效", "默认为空", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, true)]
    [EWRAOutputDesc("返回结果", @"如果是授权无效的情况下，返回400错，其它情况的返回结果集（状态为200）如下：{
code:'success-成功，failed-失败',
msg:'提示信息',
is_last_level:'表示是否为最后一级'
data:[{
code:'值',
text:'显示文本',
can_select:'表示该值是否允许被选，级联是需要选到目标资料集中的数据，而不是选择中间数据'
}]")]
    object GetCadecaseSelectMS(string id, string column_name)
    {
        string start_level_column = ComFunc.nvl(PostDataD.start_level_column);
        string start_level_value = ComFunc.nvl(PostDataD.start_level_value);
        var is_filter_deleted = BoolStd.IsNotBoolThen(PostDataD.is_filter_deleted, true);
        string parent_pk = ComFunc.nvl(PostDataD.parent_pk);
        int parent_level = IntStd.IsNotIntThen(PostDataD.parent_level, 0);
        string start_meta_name = ComFunc.nvl(PostDataD.start_meta_name);
        if (parent_pk == "") parent_level = 0;


        SetCacheEnable(false);
        var metaup = DB.NewMetaUnitParameter();
        var up = DB.NewDBUnitParameter();
        var metainfo = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA_COLUMNS", "a")
                        where t.MetaUID == id && t.MetaColumnName == column_name
                        select new
                        {
                            data_type = t.MetaDataType,
                            reference = t.MetaReference
                        }).GetQueryList(metaup);
        if (metainfo.Count <= 0)
        {
            return new
            {
                code = "failed",
                msg = "相关栏位资料不存在，无法继续进行操作"
            };
        }
        var data_type = ComFunc.nvl(metainfo.First().GetValue("data_type"));
        var column_ref = ComFunc.nvl(metainfo.First().GetValue("reference"));
        if (column_ref == "")
        {
            return new
            {
                code = "failed",
                msg = "相关栏位缺少关联数据，无法继续进行操作"
            };
        }

        var refResult = ref_express.ParseExpress(column_ref);
        if (refResult == null)
        {
            return new
            {
                code = "failed",
                msg = "相关栏位关联信息描述存在错误，无法继续进行操作"
            };
        }
        var data = new List<FrameDLRObject>();
        //根据ref表达式抓取定位table的名称
        var dbexpress = refResult.ToDBExpress(null);
        var tablename = refResult.TableName;
        var needed_tree_tables = BuildCadecaseMS_MetaTreeInfo(metaup, tablename);
        FrameDLRObject start_table_info = needed_tree_tables.Where(w => w.level == 1).FirstOrDefault();
        if (start_meta_name != "")
        {
            start_table_info = needed_tree_tables.Where(w => w.MetaName == start_meta_name).FirstOrDefault();
        }
        if (start_table_info == null)
        {
            return new
            {
                code = "failed",
                msg = "未找到起始元数据表资料"
            };
        }
        //计算parent_level真实level
        parent_level = IntStd.IsNotIntThen(start_table_info.GetValue("level"), 1) - 1 + parent_level;
        FrameDLRObject tableinfo = needed_tree_tables.Where(w => w.level == parent_level + 1).FirstOrDefault();
        if (tableinfo == null) return new
        {
            code = "failed",
            msg = "未找到指定层级元数据表"
        };
        var table = ComFunc.nvl(tableinfo.GetValue("MetaName"));
        //showcolumn需要从下级表中抓取，如果table==refResult.TableName时，则showcolumn为refResult.TextColumn
        string show_column = "_default_pk";
        if (table == refResult.TableName)
        {
            if (!string.IsNullOrEmpty(refResult.TextColumn))
                show_column = refResult.TextColumn;
        }
        else
        {
            var nexttableinfo = needed_tree_tables.Where(w => w.level == parent_level + 2).FirstOrDefault();
            if (nexttableinfo != null)
            {
                if (ComFunc.nvl(nexttableinfo.GetValue("MetaMainShowColumn")) != "")
                    show_column = ComFunc.nvl(nexttableinfo.GetValue("MetaMainShowColumn"));
            }
        }
        data = (from t in DB.LamdaTable(up, table, "a")
                where t.notnull(parent_pk, t._default_ref == parent_pk)
                && t.iftrue(parent_pk == "" && start_level_column != "" && start_level_value != "", t.column(start_level_column).within(start_level_value))
                && t.iftrue(is_filter_deleted, t._is_deleted == 0)
                orderby t.sort_no, t.column(show_column)
                select new
                {
                    code = t._default_pk,
                    text = t.column(show_column)
                }).GetQueryList(up).Select(d =>
                {
                    if (show_column == "_default_pk")
                        d.text = $"{d.code}(此处未设定显示栏位;1.设定主从表关系时，需要设定主表的显示栏位;2.请在元数据结构维护中，设定关联关系中的[关联展示字段])";
                    return d;
                }).ToList();
        foreach (dynamic item in data)
        {
            item.can_select = table == tablename;
        }

        return new
        {
            code = "success",
            msg = "",
            is_last_level = table == tablename,
            data
        };
    }
    [EWRARouteDesc("获取单表级联下拉框的内容，逐级获取")]
    [EWRARoute("post", "/metadataset/cadecase_tree/{id}/{column_name}")]
    [EWRAAddInput("is_filter_deleted", "bool", "是否过滤掉逻辑删除的资料", "默认为true", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("id", "string", "元数据表的uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAAddInput("column_name", "string", "指定栏位的名称", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAAddInput("parent_pk", "string", "上一级资料的PK", "为空时则表示拉出一级列表", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("parent_level", "int", "上一级资料的层级，从0开始", "为空时默认为0，表示拉出一级列表", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("start_level_column", "string", "起始层的栏位名称，parent_pk为空且start_level_column和start_level_value都有值才会生效", "默认为空", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, true)]
    [EWRAAddInput("start_level_value", "string", "起始层的栏位值，多个用逗号分隔,parent_pk为空且start_level_column和start_level_value都有值才会生效", "默认为空", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, true)]
    [EWRAAddInput("fixed_orderby_express", "string", "固定排序表达式，采用DBExpress的$orderby表达式写法，传入时采用base64+urlcode编码方式", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("this_data", "string", @"页面上当前编辑的行资料，先采用url编码，再采用base64编码，原数据格式:
{
    column_name1:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    column_name2:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    .....
    column_nameN:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
}", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAOutputDesc("返回结果", @"如果是授权无效的情况下，返回400错，其它情况的返回结果集（状态为200）如下：{
code:'success-成功，failed-失败',
msg:'提示信息',
data:[{
code:'值',
text:'显示文本'
}]")]
    object GetCadeCaseTree(string id, string column_name)
    {
        string start_level_column = ComFunc.nvl(PostDataD.start_level_column);
        string start_level_value = ComFunc.nvl(PostDataD.start_level_value);
        string fixed_orderby_express = ComFunc.UrlDecode(ComFunc.IsBase64Then(PostDataD.fixed_orderby_express));
        var orderby_fixed_filter_express = FrameDLRObject.IsJsonThen(fixed_orderby_express, null, FrameDLRFlags.SensitiveCase);
        var is_filter_deleted = BoolStd.IsNotBoolThen(PostDataD.is_filter_deleted, true);
        string parent_pk = ComFunc.nvl(PostDataD.parent_pk);
        int parent_level = IntStd.IsNotIntThen(PostDataD.parent_level, 1);
        if (parent_pk == "") parent_level = 0;

        SetCacheEnable(false);
        var metaup = DB.NewMetaUnitParameter();
        var up = DB.NewDBUnitParameter();
        var metainfo = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA_COLUMNS", "a")
                        where t.MetaUID == id && t.MetaColumnName == column_name
                        select new
                        {
                            data_type = t.MetaDataType,
                            reference = t.MetaReference
                        }).GetQueryList(metaup);
        if (metainfo.Count <= 0)
        {
            return new
            {
                code = "failed",
                msg = "相关栏位资料不存在，无法继续进行操作"
            };
        }
        var data_type = ComFunc.nvl(metainfo.First().GetValue("data_type"));
        var column_ref = ComFunc.nvl(metainfo.First().GetValue("reference"));
        if (column_ref == "")
        {
            return new
            {
                code = "failed",
                msg = "相关栏位缺少关联数据，无法继续进行操作"
            };
        }

        var refResult = ref_express.ParseExpress(column_ref);
        if (refResult == null)
        {
            return new
            {
                code = "failed",
                msg = "相关栏位关联信息描述存在错误，无法继续进行操作"
            };
        }
        var column_value_key = ComFunc.nvl(refResult.KeyColumn);

        var data_str = ComFunc.nvl(PostDataD.this_data).Replace(" ", "+");
        var this_data_base64str = ComFunc.IsBase64Then(data_str);
        string this_data_str = ComFunc.UrlDecode(this_data_base64str);
        var this_data = FrameDLRObject.IsJsonThen(this_data_str);
        if (data_str != "" && (this_data_str == "" || this_data == null))
        {
            return new
            {
                code = "failed",
                msg = "当前行资料格式不正确"
            };
        }
        var ref_data_str = ComFunc.nvl(PostDataD.ref_data).Replace(" ", "+");
        var ref_this_data_base64str = ComFunc.IsBase64Then(ref_data_str);
        string ref_this_data_str = ComFunc.UrlDecode(ref_this_data_base64str);
        var ref_data = FrameDLRObject.IsJsonThen(ref_this_data_str);
        if (ref_data_str != "" && (ref_this_data_str == "" || ref_data == null))
        {
            return new
            {
                code = "failed",
                msg = "父节点资料格式不正确"
            };
        }
        //获取元数据表定义的资料
        var tablename = refResult.TableName;

        var tablelist = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
                         where t.metaname == tablename && t.IsCreated == 1
                         select new
                         {
                             meta_uid = t.MetaUID,
                             meta_name = t.MetaName,
                             is_dic = 0
                         }).GetQueryList(up);
        tablelist.AddRange((from t in DB.LamdaTable(metaup, "EXTEND_DICTIONARY_TABLE", "a")
                            where t.DIC_Name == tablename && t.IsCreated == 1
                            select new
                            {
                                meta_uid = t.DIC_UID,
                                meta_name = t.DIC_Name,
                                is_dic = 1
                            }).GetQueryList(up));
        var tableinfo = tablelist.Where(w => w.meta_name == tablename).FirstOrDefault();
        if (tableinfo == null)
        {
            return new
            {
                code = "failed",
                msg = "关联表不存在或未创建"
            };
        }
        var is_dic = BoolStd.IsNotBoolThen(tableinfo.GetValue("is_dic"));



        var data = new List<FrameDLRObject>();
        UnitDataCollection result = null;
        var dbexpress = refResult.ToDBExpress(this_data, false, null, true);

        FrameDLRObject where = (parent_pk != "" || dbexpress.GetValue("$where") == null) ? FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase) : (FrameDLRObject)dbexpress.GetValue("$where");
        var parenet_uid = "";



        if (!is_dic)
        {
            if (column_value_key == "") column_value_key = "_default_pk";
            //获取起始层级
            if (column_value_key == "_default_pk")
            {
                parenet_uid = parent_pk;
            }
            else
            {
                dynamic parentinfo = (from t in DB.LamdaTable(up, tablename, "a")
                                      where t.column(column_value_key) == parent_pk
                                      select t).GetQueryList(up).FirstOrDefault();
                if (parentinfo != null)
                {
                    parenet_uid = parentinfo._default_pk;
                }
            }

            dbexpress.SetValue("_default_pk", true);
            where.SetValue("_default_parent_pk", parenet_uid);
        }
        else
        {
            if (column_value_key == "") column_value_key = "code";
            if (column_value_key == "code")
            {
                parenet_uid = parent_pk;
            }
            else
            {
                dynamic parentinfo = (from t in DB.LamdaTable(up, tablename, "a")
                                      where t.column(column_value_key) == parent_pk
                                      select t).GetQueryList(up).FirstOrDefault();
                if (parentinfo != null)
                {
                    parenet_uid = parentinfo.code;
                }
            }

            dbexpress.SetValue("code", true);
            where.SetValue("p_code", parenet_uid);
        }
        //过滤一级列表
        if (parenet_uid == "" && start_level_column != "" && start_level_value != "")
        {
            where.SetValue(start_level_column, FrameDLRObject.CreateInstanceFromat(@"{
'$in':{0}
}", start_level_value.Split(",")));
        }
        //过滤逻辑删除的资料
        if (is_filter_deleted && !is_dic)
        {
            where.SetValue("_is_deleted", 0);
        }
        dbexpress.SetValue("$where", where);
        //order by
        FrameDLRObject orderby = orderby_fixed_filter_express == null ? FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase) : orderby_fixed_filter_express;
        orderby.SetValue("sort_no", "asc");
        dbexpress.SetValue("$orderby", orderby);

        result = DB.Excute(up, dbexpress, true);
        data = result.QueryData<FrameDLRObject>().Select(d =>
        {
            FrameDLRObject dobj = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);
            dobj.SetValue("code", ComFunc.nvl(d.GetValue(column_value_key)));
            if (string.IsNullOrEmpty(refResult.TextColumn))
            {
                dobj.SetValue("text", $"{dobj.GetValue("code")}(请在元数据结构维护中，设定关联关系中的[关联展示字段])");
            }
            else
            {
                dobj.SetValue("text", d.GetValue(refResult.TextColumn));
            }


            return dobj;
        }).ToList();


        return new
        {
            code = "success",
            msg = "",
            data
        };

    }

    [ActionAuth("MetaData")]
    [EWRARouteDesc("获取指定元数据表中的数据列表")]
    [EWRAAddInput("id", "string", "元数据表uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAAddInput("mode", "string", "查询模式，Normal:普通模式，翻页查询（需要提供翻页参数）；1000：抓取前1000笔资料；All:抓取所有资料", "默认为Normal", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAAddInput("limit", "int", "每页笔数，当mode为Normal时需要提供", "默认为10", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAAddInput("page", "int", "指定页数，当mode为Normal时需要提供", "默认为1", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAAddInput("filter_column", "string", "过滤条件的栏位名称", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAAddInput("filter_op", "string", "过滤条件的操作符号，类型如下：eq:等于，gt：大于，gte：大于等于，lt：小于，lte：小于等于，like:模糊比对", "默认为eq", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAAddInput("filter_value", "string", "过滤条件的值", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, true)]
    [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
columns:[{
    column_name:'栏位名称,英文字符',
    column_desc:'栏位描述，中文描述',
    data_type:'栏位类型',
    is_allow_empty:'是否为允许为空，不允许为空时，必须做必输检查',
    is_pk:'是否为PK栏位',
    reference:'栏位关联的信息，该关联信息只适用于一对一的关联，一对多不适用，格式为：
                默认的格式(普通格式，返回值为【关联栏位名称】的值，如果没有设定则表示返回值由UI来决定)
                ',
    sort_num:'栏位排序编号',
    ui_type:'UI类型，所有的类型见相关说明',
    format:'格式化设定'
}],
total_count:'总笔数',
page:'当前页数',
total_page:'总页数',
limit:'每页笔数',
data:[元数据的结果集]
}")]
    public override object get(string id)
    {
        SetCacheEnable(false);

        string mode = ComFunc.nvl(QueryStringD.mode);
        string filter_column = ComFunc.nvl(QueryStringD.filter_column);
        string filter_op = ComFunc.nvl(QueryStringD.filter_op);
        string filter_value = ComFunc.nvl(QueryStringD.filter_value);

        if (!string.IsNullOrEmpty(filter_column))
        {
            if (!new string[] { "eq", "gt", "gte", "lt", "lte", "like" }.Contains(filter_op))
            {
                return new
                {
                    code = "failed",
                    msg = "过滤条件操作不符合要求"
                };
            }
        }

        mode = string.IsNullOrEmpty(mode) ? "Normal" : mode;


        var metaup = DB.NewMetaUnitParameter();
        var up = DB.NewDBUnitParameter();
        var s = from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
                where (t.metauid == id || t.metaname == id) && t.IsCreated == 1
                select t;
        var list = s.GetQueryList(metaup);
        if (list.Count <= 0)
        {
            return new
            {
                code = "failed",
                msg = "元数据表不存在",
            };
        }
        dynamic info = list.First();
        string tablename = info.metaname;
        var columns = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA_COLUMNS", "a")
                       orderby t.sortnum
                       where t.metauid == info.metauid && t.isshow == 1 && t.IsVirsual == 0
                       select new
                       {
                           column_name = t.MetaColumnName,
                           column_desc = t.MetaColumnDesc,
                           data_type = t.MetaDataType,
                           reference = t.MetaReference,
                           is_allow_empty = t.MetaAllowEmpty,
                           is_pk = t.MetaIsPK,
                           sort_num = t.SortNum,
                           is_show = t.IsShow,
                           format = t.MetaFormat
                       }).GetQueryList(metaup);
        #region 固定带上以下栏位
        columns.AddRange(MetaDataUtilities.FixColumns);
        #endregion
        var support_data_type = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA_DATATYPE", "a")
                                 select new
                                 {
                                     data_type = t.DataType,
                                     desc = t.DataTypeDesc,
                                     is_allow_empty_zero_precision = t.IsAllowEmptyOrZero_Precision,
                                     is_allow_empty_zero_scale = t.IsAllowEmptyOrZero_Scale,
                                     is_allow_pk = t.IsAllowPK,
                                     is_auto_fix = t.IsAutoFix,
                                     auto_fix_method = t.AutoFix_Method,
                                     ui_type = t.UI_TYPE
                                 }).GetQueryList(metaup);

        var datatype_dic = columns.ToDictionary(k => k.GetValue("column_name"), v => v.GetValue("data_type"));
        #region 构建select表达式
        FrameDLRObject express = FrameDLRObject.CreateInstance(@"{
$acttype : 'QueryByPage',
$orderby : 'sort_no',
                }", EFFC.Frame.Net.Base.Constants.FrameDLRFlags.SensitiveCase);
        switch (mode)
        {
            case "1000":
                express.SetValue("$acttype", "QueryByPage");
                up.Count_Of_OnePage = 1000;
                up.ToPage = 1;
                break;
            case "All":
                express.SetValue("$acttype", "Query");
                break;
            default:
                express.SetValue("$acttype", "QueryByPage");
                break;
        }

        FrameDLRObject tableexpress = FrameDLRObject.CreateInstance(EFFC.Frame.Net.Base.Constants.FrameDLRFlags.SensitiveCase);

        foreach (dynamic c in columns)
        {
            if (BoolStd.IsNotBoolThen(c.is_show))
            {
                //设定select的栏位
                express.SetValue($"{c.column_name}", true);
                //设定是否要求输入
                c.is_allow_empty = BoolStd.IsNotBoolThen(c.is_allow_empty);
                c.is_pk = BoolStd.IsNotBoolThen(c.is_pk);
            }
        }
        express.SetValue("$table", tablename);


        if (!string.IsNullOrEmpty(filter_column))
        {
            FrameDLRObject where = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);
            FrameDLRObject exp = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);
            exp.SetValue($"${filter_op}", filter_value);
            where.SetValue(filter_column, exp);
            express.SetValue("$where", where);
        }
        #endregion
        var result = DB.Excute(up, express, true);
        var resultlist = result.QueryData<FrameDLRObject>();

        var data = resultlist.Select((p) =>
        {
            var dobj = (FrameDLRObject)p;
            foreach (var key in dobj.Keys)
            {
                var v = dobj.GetValue(key);
                dobj.SetValue(key, convert2UIValue(v, datatype_dic.ContainsKey(key) ? datatype_dic[key] : ""));
            }
            return p;
        }).ToList();

        var tablemap = getTableColumnsMap(metaup);
        var data_type_map = support_data_type.ToDictionary(k => (string)ComFunc.nvl(k.GetValue("data_type")), v => new { v.desc, v.ui_type });
        foreach (dynamic c in columns)
        {
            //根据reference和data_type设定ui_type
            c.ui_type = data_type_map.ContainsKey(ComFunc.nvl(c.data_type)) ? data_type_map[c.data_type].ui_type : "Input";
        }

        if (mode == "All")
        {
            return new
            {
                code = "success",
                msg = "",
                columns = columns,
                total_count = data.Count,
                page = 1,
                total_page = 1,
                limit = data.Count,
                data = data
            };
        }
        else
        {
            return new
            {
                code = "success",
                msg = "",
                columns = columns,
                total_count = result.TotalRow,
                page = result.CurrentPage,
                total_page = result.TotalPage,
                limit = result.Count_Of_OnePage,
                data = data
            };
        }

    }
    [ActionAuth("MetaData")]
    [EWRAEmptyValid("id,data")]
    [EWRARouteDesc("新增元数据表中的数据")]
    [EWRAAddInput("id", "string", "元数据表uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAAddInput("data", "array", @"待新增的数据列表，如果为file、picture类型,则需要先进行上传，再传入返回的文件路径，格式:
[
{
    column_name1:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    column_name2:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    .....
    column_nameN:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
}
]
", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息'
}")]
    public override object post()
    {
        var id = ComFunc.nvl(PostDataD.id);
        var data = PostDataD.data;

        if (!(data is IEnumerable<object>))
            return new
            {
                code = "failed",
                msg = "参数格式不正确",
            };
        var datalist = (IEnumerable<object>)data;
        BeginTrans();
        var metaup = DB.NewMetaUnitParameter();
        var up = DB.NewDBUnitParameter();
        var rtn = DoPost(metaup, up, id, datalist, TokenPayLoad.ID, ComFunc.nvl(TokenPayLoad["username"]), ClientInfo.IP, BoolStd.IsNotBoolThen(Configs["Is_UseLocal"]));
        CommitTrans();
        return rtn;
    }
    public object DoPost(UnitParameter metaup, UnitParameter up, string id, IEnumerable<object> data,
        string login_id = "", string login_name = "", string login_ip = "", bool is_use_local_upload = true)
    {
        var datalist = data.Select((p) =>
        {
            var dobj = (FrameDLRObject)p;
            dobj.Remove("RowNumber");
            dobj.Remove("add_id");
            dobj.Remove("add_name");
            dobj.Remove("add_ip");
            dobj.Remove("add_time");
            dobj.Remove("last_id");
            dobj.Remove("last_name");
            dobj.Remove("last_ip");
            dobj.Remove("last_time");
            return dobj;
        }).ToList();
        var s = from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
                where (t.metauid == id || t.metaname == id) && t.IsCreated == 1
                select t;
        var list = s.GetQueryList(metaup);
        if (list.Count <= 0)
        {
            return new
            {
                code = "failed",
                msg = "元数据表不存在",
            };
        }
        dynamic info = list.First();
        string tablename = info.metaname;
        var columns = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA_COLUMNS", "a")
                       join t2 in DB.LamdaTable(metaup, "EXTEND_METADATA_DATATYPE", "b").LeftJoin() on t.MetaDataType equals t2.DataType
                       where t.metauid == info.metauid && t.IsVirsual == 0
                       select new
                       {
                           column_name = t.MetaColumnName,
                           column_desc = t.MetaColumnDesc,
                           is_pk = t.MetaIsPK,
                           data_type = t.MetaDataType,
                           is_allow_empty = t.MetaAllowEmpty,
                           precision = t.MetaDataPrecision,
                           format = t.MetaFormat,
                           map_dbtype = t2.Map_DBType
                       }).GetQueryList(metaup);
        //固定带上
        columns.AddRange(MetaDataUtilities.FixColumns);
        //目前系统支持的数据类型及相关约束
        var support_data_type = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA_DATATYPE", "a")
                                 select new
                                 {
                                     data_type = t.DataType,
                                     desc = t.DataTypeDesc,
                                     is_allow_empty_zero_precision = t.IsAllowEmptyOrZero_Precision,
                                     is_allow_empty_zero_scale = t.IsAllowEmptyOrZero_Scale,
                                     is_allow_pk = t.IsAllowPK,
                                     is_auto_fix = t.IsAutoFix,
                                     auto_fix_method = t.AutoFix_Method,
                                     ui_type = t.UI_TYPE,
                                     map_dbtype = t.Map_DBType
                                 }).GetQueryList(metaup);

        var column_names = columns.Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_int = columns.Where(w => w.map_dbtype == "int").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_numbric = columns.Where(w => w.map_dbtype == "numberic").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_bit = columns.Where(w => w.map_dbtype == "bit").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_datetime = columns.Where(w => !(new string[] { "time", "date_year", "date_year_month" }.Contains((string)ComFunc.nvl(w.data_type))) && ComFunc.nvl(w.map_dbtype) == "datetime").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_time = columns.Where(w => ComFunc.nvl(w.data_type) == "time" && ComFunc.nvl(w.map_dbtype) == "datetime").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_dateyear = columns.Where(w => ComFunc.nvl(w.data_type) == "date_year" && ComFunc.nvl(w.map_dbtype) == "datetime").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_dateyearmonth = columns.Where(w => ComFunc.nvl(w.data_type) == "date_year_month" && ComFunc.nvl(w.map_dbtype) == "datetime").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var pkcolumns = columns.Where(p => BoolStd.IsNotBoolThen(p.is_pk, false)).Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var notemptycolumns = columns.Where(p => !BoolStd.IsNotBoolThen(p.is_allow_empty, true)).Select((p) =>
        {
            return new
            {
                column_name = ComFunc.nvl(p.GetValue("column_name")),
                column_desc = ComFunc.nvl(p.GetValue("column_desc"))
            };
        }).ToList();
        //系统自动填入参数的栏位
        var auto_fix_datatype = support_data_type.Where(w => BoolStd.IsNotBoolThen(w.is_auto_fix));
        var auto_fix_string = auto_fix_datatype.Select(d => ComFunc.nvl(((FrameDLRObject)d).GetValue("data_type"))).ToArray();
        var auto_fix_columns = columns.Where(p => auto_fix_string.Contains((string)ComFunc.nvl(p.data_type))).Select((p) =>
        {
            return new
            {
                column_name = ComFunc.nvl(p.GetValue("column_name")),
                data_type = ComFunc.nvl(p.GetValue("data_type")),
                is_allow_empty = BoolStd.IsNotBoolThen(p.GetValue("is_allow_empty"), true),
                precision = IntStd.IsNotIntThen(p.GetValue("precision"), 0),
                format = ComFunc.nvl(p.GetValue("format"))
            };
        }).ToList();
        //系统自动填入数据的栏位
        foreach (FrameDLRObject d in datalist)
        {
            //去除RowNumber
            d.Remove("RowNumber");

            foreach (var c in auto_fix_columns)
            {
                if (ComFunc.nvl(d.GetValue(c.column_name)) == ""
                    && !c.is_allow_empty)
                {
                    var dts = auto_fix_datatype.Where(w => w.data_type == c.data_type);
                    if (dts.Count() > 0)
                    {
                        var auto_fix_method = ComFunc.nvl(dts.First().GetValue("auto_fix_method"));
                        if (auto_fix_method == "AutoCode")
                        {
                            d.SetValue(c.column_name, genAutoCode(up, tablename, c.column_name, ComFunc.nvl(c.format)));
                        }
                        else
                        {
                            d.SetValue(c.column_name, genAutoFixValue(auto_fix_method, c.precision));
                        }
                    }
                }
            }
        }
        //栏位检查
        foreach (FrameDLRObject d in datalist)
        {
            foreach (var ne in notemptycolumns)
            {
                if (ComFunc.nvl(d.GetValue(ne.column_name)) == "")
                {
                    return new
                    {
                        code = "failed",
                        msg = $"{ne.column_desc}栏位不可为空",
                    };
                }
            }
            if ((from t in d.Keys
                 join t2 in pkcolumns on t equals t2
                 select t).Count() != pkcolumns.Count)
            {
                return new
                {
                    code = "failed",
                    msg = "数据缺少PK栏位的数据，无法进行数据新增",
                };
            }
            foreach (var key in d.Keys)
            {
                if (!column_names.Contains(key))
                {
                    return new
                    {
                        code = "failed",
                        msg = "数据栏位不匹配",
                    };
                }
                //数据类型检查
                if (column_int.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !IntStd.IsInt(d.GetValue(key)))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"值({d.GetValue(key)})不是int类型",
                    };
                }
                if (column_numbric.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !DecimalStd.IsDecimal(d.GetValue(key)))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"({d.GetValue(key)})不是numberic类型",
                    };
                }
                if (column_bit.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !BoolStd.IsBool(d.GetValue(key)))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"({d.GetValue(key)})不是bit类型",
                    };
                }
                if (column_datetime.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !DateTimeStd.IsDateTime(d.GetValue(key)))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"({d.GetValue(key)})不是datetime类型",
                    };
                }
                if (column_time.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !DateTimeStd.IsDateTime(d.GetValue(key), "HH:mm:ss"))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"({d.GetValue(key)})不是time类型",
                    };
                }
                if (column_dateyear.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !DateTimeStd.IsDateTime(d.GetValue(key), "yyyy") && !DateTimeStd.IsDateTime(d.GetValue(key)))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"({d.GetValue(key)})不是date_year类型",
                    };
                }
                if (column_dateyearmonth.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !DateTimeStd.IsDateTime(d.GetValue(key), "yyyy-M") && !DateTimeStd.IsDateTime(d.GetValue(key), "yyyy-MM") && !DateTimeStd.IsDateTime(d.GetValue(key)))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"({d.GetValue(key)})不是date_year类型",
                    };
                }
            }


        }
        //有pk设定的时候做检查，排除_default_pk
        if (pkcolumns.Count > 1)
        {
            foreach (FrameDLRObject d in datalist)
            {
                //pk栏位不可为空

                FrameDLRObject w = FrameDLRObject.CreateInstance();
                foreach (var pk in pkcolumns)
                {
                    if (pk == "_default_pk") continue;
                    if (ComFunc.nvl(d.GetValue(pk)) == "")
                    {
                        return new
                        {
                            code = "failed",
                            msg = "PK栏位不可为空",
                        };
                    }
                    w.SetValue(pk, d.GetValue(pk));
                }
                FrameDLRObject express = FrameDLRObject.CreateInstance($@"{{
$acttype : 'Query',
$table:'{tablename}'
}}");
                express.SetValue("$where", w);
                if (DB.Excute(up, express).QueryTable.RowLength > 0)
                {
                    return new
                    {
                        code = "failed",
                        msg = "数据重复，不能继续进行操作",
                    };
                }
            }
        }
        foreach (FrameDLRObject d in datalist)
        {
            foreach (dynamic cc in columns)
            {
                d.SetValue(cc.column_name, convert2DBValue(d.GetValue(cc.column_name), cc.data_type));
            }
            //设置默认状态为0-保存
            d.SetValue("_status", MetaStatus.Save);
            //设置启用为false
            d.SetValue("_active", 0);
            //设置资料锁定状态为0
            d.SetValue("_lock", MetaLock.UnLock);
            //设置逻辑删除标记
            d.SetValue("_is_deleted", 0);
            d.SetValue("_default_parent_pk", ComFunc.nvl(d.GetValue("_default_parent_pk")));
            //增加操作者的信息
            d.SetValue("add_id", login_id);
            d.SetValue("add_ip", login_ip);
            d.SetValue("add_name", login_name);
            d.SetValue("add_time", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            d.SetValue("last_id", login_id);
            d.SetValue("last_ip", login_ip);
            d.SetValue("last_name", login_name);
            d.SetValue("last_time", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            DB.QuickInsert(up, tablename, d);
        }
        return new
        {
            code = "success",
            msg = "操作成功",
        };
    }
    [ActionAuth("MetaData")]
    [EWRAEmptyValid("data")]
    [EWRARouteDesc("删除元数据表中的数据")]
    [EWRAAddInput("id", "string", "元数据表uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAAddInput("data", "array", @"待删除的数据列表，格式:
[
{
    column_name1:'值',
    column_name2:'值',
    .....
    column_nameN:'值',
}
]", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAOutputDesc("返回结果", @"根据http的状态码来识别，204标识操作成功，404表示操作识别未找到删除的资料")]
    public override bool delete(string id)
    {
        var data = PostDataD.data;
        if (!(data is IEnumerable<object>))
        {
            return false;
        }
        var datalist = (IEnumerable<object>)data;

        BeginTrans();
        var metaup = DB.NewMetaUnitParameter();
        var up = DB.NewDBUnitParameter();
        var rtn = DoDelete(metaup, up, id, datalist, BoolStd.IsNotBoolThen(Configs["Is_UseLocal"]));
        CommitTrans();
        return rtn;
    }
    public bool DoDelete(UnitParameter metaup, UnitParameter up, string id, IEnumerable<object> data, bool is_use_local_upload = true)
    {
        var datalist = data.Select((d) =>
        {
            var dobj = (FrameDLRObject)d;
            dobj.Remove("RowNumber");
            dobj.Remove("add_id");
            dobj.Remove("add_name");
            dobj.Remove("add_ip");
            dobj.Remove("add_time");
            dobj.Remove("last_id");
            dobj.Remove("last_name");
            dobj.Remove("last_ip");
            dobj.Remove("last_time");
            return dobj;
        }).ToList();
        var s = from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
                where (t.metauid == id || t.metaname == id) && t.IsCreated == 1
                select t;
        var list = s.GetQueryList(metaup);
        if (!(from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
              where (t.metauid == id || t.metaname == id) && t.IsCreated == 1
              select t).IsExists(metaup))
        {
            return false;
        }
        dynamic info = list.First();
        string tablename = info.metaname;
        var columns = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA_COLUMNS", "a")
                       where t.metauid == info.metauid && t.IsVirsual == 0
                       select new
                       {
                           column_name = t.MetaColumnName,
                           is_pk = t.MetaIsPK,
                           data_type = t.MetaDataType
                       }).GetQueryList(metaup);
        //固定带上sort_no
        columns.AddRange(MetaDataUtilities.FixColumns);

        var column_names = columns.Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var pkcolumns = columns.Where(p => BoolStd.IsNotBoolThen(p.is_pk, false)).Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        //栏位检查
        foreach (FrameDLRObject d in datalist)
        {
            foreach (var key in d.Keys)
            {
                if (!column_names.Contains(key))
                {
                    return false;
                }
            }
        }
        string[] filecolumns = columns.Where(w => new string[] { "file", "picture" }.Contains((string)w.data_type)).Select(d => ComFunc.nvl(d.GetValue("column_name"))).ToArray();
        string[] multifilecolumns = columns.Where(w => new string[] { "multi-file", "pictures" }.Contains((string)w.data_type)).Select(d => ComFunc.nvl(d.GetValue("column_name"))).ToArray();
        foreach (FrameDLRObject d in datalist)
        {
            var delfilepath = new List<string>();
            foreach (var c in filecolumns)
            {
                var v = ComFunc.nvl(d.GetValue(c));
                if (v != "") delfilepath.Add(v);
            }
            foreach (var c in multifilecolumns)
            {
                var v = FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(d.GetValue(c)), new object[] { });
                if (v != null) delfilepath.AddRange(v.Select(d => ComFunc.nvl(d)));
            }

            //按照pk进行资料删除，每笔资料都有一个_default_pk
            FrameDLRObject w = FrameDLRObject.CreateInstance();
            foreach (var pkc in pkcolumns)
            {
                w.SetValue(pkc, d.GetValue(pkc));
            }
            DB.QuickDelete(up, tablename, w);
        }
        return true;
    }
    [ActionAuth("MetaData")]
    [EWRARoute("delete", "/metadataset/{id}/all")]
    [EWRARouteDesc("删除指定元数据表中的所有数据")]
    [EWRAAddInput("id", "string", "元数据表uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAOutputDesc("返回结果", @"根据http的状态码来识别，204标识操作成功，404表示操作识别未找到删除的资料")]
    public bool DeleteAll(string id)
    {
        BeginTrans();
        var metaup = DB.NewMetaUnitParameter();
        var up = DB.NewDBUnitParameter();
        var rtn = DoDeleteALl(metaup, up, id);
        CommitTrans();
        return rtn;
    }
    public bool DoDeleteALl(UnitParameter metaup, UnitParameter up, string id)
    {
        var s = from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
                where (t.metauid == id || t.metaname == id) && t.IsCreated == 1
                select t;
        var list = s.GetQueryList(metaup);
        if (!(from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
              where (t.metauid == id || t.metaname == id) && t.IsCreated == 1
              select t).IsExists(metaup))
        {
            return false;
        }
        dynamic info = list.First();
        string tablename = info.metaname;
        (from t in DB.LamdaTable(up, tablename, "a")
         select t).Delete(up);

        return true;
    }
    [ActionAuth("MetaData")]
    [EWRAEmptyValid("data,ori_data")]
    [EWRARouteDesc("修改元数据表中的数据")]
    [EWRAAddInput("id", "string", "元数据表uid", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.Path, false)]
    [EWRAAddInput("ori_data", "array", @"未修改的原始数据数据的条件，如果为file、picture类型,则需要先进行上传，再传入返回的文件路径，格式:
[
{
    column_name1:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    column_name2:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    .....
    column_nameN:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
}
]", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAAddInput("data", "array", @"待修改的数据列表，该数组中的每笔资料必须与ori_data中的下标和栏位都一致，如果为file、picture类型,则需要先进行上传，再传入返回的文件路径，格式:
[
{
    column_name1:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    column_name2:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
    .....
    column_nameN:'值，如果为file、picture类型则值的格式内容为上传后的文件路径',
}
]", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息'
}")]
    public override object patch(string id)
    {
        var data = PostDataD.data;
        var ori_data = PostDataD.ori_data;
        if (!(data is IEnumerable<object>) || !(ori_data is IEnumerable<object>))
        {
            return new
            {
                code = "failed",
                msg = "参数格式不正确",
            };
        }
        var datalist = (IEnumerable<object>)data;
        var ori_datalist = (IEnumerable<object>)ori_data;
        var metaup = DB.NewMetaUnitParameter();
        var up = DB.NewDBUnitParameter();
        BeginTrans();
        var rtn = DoPatch(metaup, up, id, datalist, ori_datalist, TokenPayLoad.ID, ComFunc.nvl(TokenPayLoad["username"]), ClientInfo.IP, BoolStd.IsNotBoolThen(Configs["Is_UseLocal"]));
        CommitTrans();
        return rtn;
    }

    public object DoPatch(UnitParameter metaup, UnitParameter up, string id, IEnumerable<object> data, IEnumerable<object> ori_data,
        string login_id = "", string login_name = "", string login_ip = "", bool is_use_local_upload = true)
    {
        var datalist = data.Select((p) =>
        {
            var dobj = (FrameDLRObject)p;
            dobj.Remove("RowNumber");
            dobj.Remove("add_id");
            dobj.Remove("add_name");
            dobj.Remove("add_ip");
            dobj.Remove("add_time");
            dobj.Remove("last_id");
            dobj.Remove("last_name");
            dobj.Remove("last_ip");
            dobj.Remove("last_time");
            return dobj;
        }).ToList();
        var oridatalist = ori_data.Select((p) =>
        {
            var dobj = (FrameDLRObject)p;
            dobj.Remove("RowNumber");
            dobj.Remove("add_id");
            dobj.Remove("add_name");
            dobj.Remove("add_ip");
            dobj.Remove("add_time");
            dobj.Remove("last_id");
            dobj.Remove("last_name");
            dobj.Remove("last_ip");
            dobj.Remove("last_time");
            return dobj;
        }).ToList(); ;
        if (datalist.Count() != oridatalist.Count())
        {
            return new
            {
                code = "failed",
                msg = "ori_data与data的数据不一致",
            };
        }
        for (var i = 0; i < datalist.Count(); i++)
        {
            if (datalist[i].Keys.Count != oridatalist[i].Keys.Count)
            {
                return new
                {
                    code = "failed",
                    msg = "ori_data与data的数据不一致",
                };
            }
        }

        for (int i = 0; i < datalist.Count(); i++)
        {
            if ((from t in datalist[i].Keys join t2 in oridatalist[i].Keys on t equals t2 select t).Count() != datalist[i].Keys.Count)
            {
                return new
                {
                    code = "failed",
                    msg = "ori_data与data的数据不一致",
                };
            }
        }

        var s = from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
                where (t.metauid == id || t.metaname == id) && t.IsCreated == 1
                select t;
        var list = s.GetQueryList(metaup);
        if (list.Count <= 0)
        {
            return new
            {
                code = "failed",
                msg = "元数据表不存在",
            };
        }
        dynamic info = list.First();
        string tablename = info.metaname;
        var columns = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA_COLUMNS", "a")
                       join t2 in DB.LamdaTable(metaup, "EXTEND_METADATA_DATATYPE", "b").LeftJoin() on t.MetaDataType equals t2.DataType
                       where t.metauid == info.metauid && t.IsVirsual == 0
                       select new
                       {
                           column_name = t.MetaColumnName,
                           column_desc = t.MetaColumnDesc,
                           is_pk = t.MetaIsPK,
                           data_type = t.MetaDataType,
                           is_allow_empty = t.MetaAllowEmpty,
                           precision = t.MetaDataPrecision,
                           format = t.MetaFormat,
                           map_dbtype = t2.Map_DBType
                       }).GetQueryList(metaup);
        //固定带上栏位
        columns.AddRange(MetaDataUtilities.FixColumns);
        //目前系统支持的数据类型及相关约束
        var support_data_type = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA_DATATYPE", "a")
                                 select new
                                 {
                                     data_type = t.DataType,
                                     desc = t.DataTypeDesc,
                                     is_allow_empty_zero_precision = t.IsAllowEmptyOrZero_Precision,
                                     is_allow_empty_zero_scale = t.IsAllowEmptyOrZero_Scale,
                                     is_allow_pk = t.IsAllowPK,
                                     is_auto_fix = t.IsAutoFix,
                                     auto_fix_method = t.AutoFix_Method,
                                     ui_type = t.UI_TYPE
                                 }).GetQueryList(metaup);

        var column_names = columns.Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_int = columns.Where(w => w.data_type == "int").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_numbric = columns.Where(w => w.data_type == "numberic").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_bit = columns.Where(w => w.data_type == "bit").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_datetime = columns.Where(w => !(new string[] { "time", "date_year", "date_year_month" }.Contains((string)ComFunc.nvl(w.data_type))) && ComFunc.nvl(w.map_dbtype) == "datetime").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_time = columns.Where(w => ComFunc.nvl(w.data_type) == "time" && ComFunc.nvl(w.map_dbtype) == "datetime").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_dateyear = columns.Where(w => ComFunc.nvl(w.data_type) == "date_year" && ComFunc.nvl(w.map_dbtype) == "datetime").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var column_dateyearmonth = columns.Where(w => ComFunc.nvl(w.data_type) == "date_year_month" && ComFunc.nvl(w.map_dbtype) == "datetime").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        var notemptycolumns = columns.Where(p => !BoolStd.IsNotBoolThen(p.is_allow_empty, true)).Select((p) =>
        {
            return new
            {
                column_name = ComFunc.nvl(p.GetValue("column_name")),
                column_desc = ComFunc.nvl(p.GetValue("column_desc"))
            };
        }).ToList();
        //系统自动填入参数的栏位
        var auto_fix_datatype = support_data_type.Where(w => BoolStd.IsNotBoolThen(w.is_auto_fix));
        var auto_fix_string = auto_fix_datatype.Select(d => ComFunc.nvl(((FrameDLRObject)d).GetValue("data_type"))).ToArray();
        var auto_fix_columns = columns.Where(p => auto_fix_string.Contains((string)ComFunc.nvl(p.data_type))).Select((p) =>
        {
            return new
            {
                column_name = ComFunc.nvl(p.GetValue("column_name")),
                data_type = ComFunc.nvl(p.GetValue("data_type")),
                is_allow_empty = BoolStd.IsNotBoolThen(p.GetValue("is_allow_empty"), true),
                precision = IntStd.IsNotIntThen(p.GetValue("precision"), 0),
                format = ComFunc.nvl(p.GetValue("format"))
            };
        }).ToList();
        var pkcolumns = columns.Where(p => BoolStd.IsNotBoolThen(p.is_pk, true) && p.data_type != "text").Select((p) => { return ComFunc.nvl(p.GetValue("column_name")); }).ToList();
        //系统自动填入数据的栏位
        foreach (FrameDLRObject d in datalist)
        {
            foreach (var c in auto_fix_columns)
            {
                if (ComFunc.nvl(d.GetValue(c.column_name)) == ""
                    && !c.is_allow_empty)
                {
                    var dts = auto_fix_datatype.Where(w => w.data_type == c.data_type);
                    if (dts.Count() > 0)
                    {
                        var auto_fix_method = ComFunc.nvl(dts.First().GetValue("auto_fix_method"));
                        if (auto_fix_method == "AutoCode")
                        {
                            d.SetValue(c.column_name, genAutoCode(up, tablename, c.column_name, ComFunc.nvl(c.format)));
                        }
                        else
                        {
                            d.SetValue(c.column_name, genAutoFixValue(auto_fix_method, c.precision));
                        }
                    }
                }
            }
        }
        var index = -1;
        //栏位检查
        foreach (FrameDLRObject d in datalist)
        {
            index++;
            foreach (var ne in notemptycolumns)
            {
                if (ComFunc.nvl(d.GetValue(ne.column_name)) == "")
                {
                    return new
                    {
                        code = "failed",
                        msg = $"{ne.column_desc}栏位不可为空",
                    };
                }
            }

            if ((from t in d.Keys
                 join t2 in pkcolumns on t equals t2
                 select t).Count() != pkcolumns.Count)
            {
                return new
                {
                    code = "failed",
                    msg = "数据缺少PK栏位的数据，无法进行数据修改",
                };
            }

            var newpkstring = "";
            var oripkstring = "";
            foreach (var pk in pkcolumns)
            {
                if (ComFunc.nvl(d.GetValue(pk)) == "")
                {
                    return new
                    {
                        code = "failed",
                        msg = "PK栏位不可为空",
                    };
                }
                newpkstring += $"{d.GetValue(pk)}|";
                oripkstring += $"{oridatalist[index].GetValue(pk)}|";
            }

            if (newpkstring != oripkstring)
            {
                return new
                {
                    code = "failed",
                    msg = "PK栏位不可修改",
                };
            }

            foreach (var key in d.Keys)
            {
                if (!column_names.Contains(key))
                {
                    return new
                    {
                        code = "failed",
                        msg = "数据栏位不匹配",
                    };
                }
                //数据类型检查
                if (column_int.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !IntStd.IsInt(d.GetValue(key)))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"值({d.GetValue(key)})不是int类型",
                    };
                }
                if (column_numbric.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !DecimalStd.IsDecimal(d.GetValue(key)))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"({d.GetValue(key)})不是numberic类型",
                    };
                }
                if (column_bit.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !BoolStd.IsBool(d.GetValue(key)))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"({d.GetValue(key)})不是bit类型",
                    };
                }
                if (column_datetime.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !DateTimeStd.IsDateTime(d.GetValue(key)))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"({d.GetValue(key)})不是datetime类型",
                    };
                }
                if (column_time.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !DateTimeStd.IsDateTime(d.GetValue(key), "HH:mm:ss"))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"({d.GetValue(key)})不是time类型",
                    };
                }
                if (column_dateyear.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !DateTimeStd.IsDateTime(d.GetValue(key), "yyyy") && !DateTimeStd.IsDateTime(d.GetValue(key)))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"({d.GetValue(key)})不是date_year类型",
                    };
                }
                if (column_dateyearmonth.Contains(key) && ComFunc.nvl(d.GetValue(key)) != "" && !DateTimeStd.IsDateTime(d.GetValue(key), "yyyy-M") && !DateTimeStd.IsDateTime(d.GetValue(key), "yyyy-MM") && !DateTimeStd.IsDateTime(d.GetValue(key)))
                {
                    return new
                    {
                        code = "failed",
                        msg = $"({d.GetValue(key)})不是date_year类型",
                    };
                }
            }
        }
        //有pk设定的时候做检查，排除_default_pk
        if (pkcolumns.Count > 1)
        {
            foreach (FrameDLRObject d in datalist)
            {
                //pk栏位不可为空

                FrameDLRObject w = FrameDLRObject.CreateInstance();
                FrameDLRObject _pk_op = FrameDLRObject.CreateInstance();
                _pk_op.SetValue("$neq", d.GetValue("_default_pk"));
                w.SetValue("_default_pk", _pk_op);

                foreach (var pk in pkcolumns)
                {
                    if (pk == "_default_pk") continue;
                    if (ComFunc.nvl(d.GetValue(pk)) == "")
                    {
                        return new
                        {
                            code = "failed",
                            msg = "PK栏位不可为空",
                        };
                    }
                    w.SetValue(pk, d.GetValue(pk));
                }
                FrameDLRObject express = FrameDLRObject.CreateInstance($@"{{
$acttype : 'Query',
$table:'{tablename}'
}}");
                express.SetValue("$where", w);
                if (DB.Excute(up, express).QueryTable.RowLength > 0)
                {
                    return new
                    {
                        code = "failed",
                        msg = "数据重复，不能继续进行操作",
                    };
                }
            }
        }
        index = -1;
        var validCount = 0;
        foreach (FrameDLRObject d in datalist)
        {
            index++;
            var isupdate = false;
            //判断是否数据没有变化，没有变化的则不做修改操作
            foreach (var k in d.Keys)
            {
                if (d.GetValue(k) == null && oridatalist[index].GetValue(k) != null)
                {
                    isupdate = true;
                    break;
                }
                if (!d.GetValue(k).Equals(oridatalist[index].GetValue(k)))
                {
                    isupdate = true;
                    break;
                }
            }
            if (!isupdate)
            {
                continue;
            }

            foreach (dynamic cc in columns)
            {
                d.SetValue(cc.column_name, convert2DBValue(d.GetValue(cc.column_name), cc.data_type));
            }
            d.Remove("add_id");
            d.Remove("add_name");
            d.Remove("add_ip");
            d.Remove("add_time");
            //增加操作者的信息
            d.SetValue("last_id", login_id);
            d.SetValue("last_ip", login_ip);
            d.SetValue("last_name", login_name);
            d.SetValue("last_time", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
            //按照pk进行更新
            FrameDLRObject w = FrameDLRObject.CreateInstance();
            foreach (var ss in pkcolumns)
            {
                w.SetValue(ss, oridatalist[index].GetValue(ss));
            }

            DB.QuickUpdate(up, tablename, d, w);

            validCount++;
        }
        return new
        {
            code = "success",
            msg = $"操作成功,更新有效数据{validCount}笔",
        };
    }
    [ActionAuth("MetaData")]
    [EWRARoute("post", "/metadataset/upload")]
    [EWRAEmptyValid("file_name,file_length,file_content")]
    [EWRARouteDesc("上传文件")]
    [EWRAAddInput("file_name", "string", "文件名称", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAAddInput("file_length", "double", "文件大小", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAAddInput("file_content", "string", "文件内容，base64加密", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
upload_path:'上传成功后返回的文档路径'
}")]
    public object Upload()
    {
        string file_name = ComFunc.nvl(PostDataD.file_name);
        long file_length = Int64Std.IsNotInt64Then(PostDataD.file_length);
        string file_content = ComFunc.nvl(PostDataD.file_content).Replace(" ", "+");
        var is_keep_filename = BoolStd.IsNotBoolThen(PostDataD.is_keep_filename);
        return FileHelper.DoUploadFile(file_name, file_length, file_content, is_keep_filename);
    }
    [EWRARoute("get", "/metadataset/dl")]
    [EWRAEmptyValid("path")]
    [EWRARouteDesc("下载文件")]
    [EWRAAddInput("path", "string", "文件路径，使用urlcode编码", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.QueryString, false)]
    [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
filetype:'文件的content-type类型'
filename:'文件名称',
filelength:'文件长度',
file:'文件内容，采用base64加密'
}")]
    public object DownLoad()
    {
        SetCacheEnable(false);
        string path = ComFunc.UrlDecode(QueryStringD.path);
        return FileHelper.DoDownLoad(path);
    }
    [EWRARoute("patch", "/metadataset/split_data")]
    [EWRARouteDesc("分隔data中的数据，转化成列表")]
    [EWRAAddInput("split_char", "string", "分隔符", "默认逗号", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("line_char", "string", "换行符", "默认\\n", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("data_txt", "string", "要分隔的数据", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
columns:['栏位名称']
data:[{
col1:'内容',
col2:'内容'
col3:'内容'
...
colN:'内容'
}]
}")]
    public object SplitData()
    {
        string split_char = ComFunc.nvlNotrim(PostDataD.split_char);
        string line_char = ComFunc.nvlNotrim(PostDataD.line_char);
        string data_txt = ComFunc.nvlNotrim(PostDataD.data_txt);
        if (data_txt == "")
        {
            return new
            {
                code = "failed",
                msg = "请输入数据"
            };
        }

        if (split_char == "") split_char = ",";
        else split_char = ConvertEscape(split_char);
        if (line_char == "") line_char = "\n";
        else line_char = ConvertEscape(line_char);

        var rows = data_txt.Split(line_char, StringSplitOptions.RemoveEmptyEntries);
        var list = new List<FrameDLRObject>();
        var columns = new List<string>();
        foreach (var r in rows)
        {
            var cols = r.Split(split_char);
            FrameDLRObject item = FrameDLRObject.CreateInstance();
            var index = 0;
            foreach (var c in cols)
            {
                var col = $"col_{index}";
                item.SetValue(col, c);
                if (!columns.Contains(col))
                {
                    columns.Add(col);
                }
                index++;
            }
            list.Add(item);
        }

        return new
        {
            code = "success",
            msg = "",
            columns,
            data = list
        };
    }
    [EWRARoute("patch", "/metadataset/split_data_matrix")]
    [EWRARouteDesc("转化矩阵中的数据，转化成列表")]
    [EWRAAddInput("split_char", "string", "分隔符", "默认逗号", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("line_char", "string", "换行符", "默认\\n", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAAddInput("data_txt", "string", "要分隔的数据", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, false)]
    [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
columns:['栏位名称']
data:[{
col1:'内容',
col2:'内容'
col3:'内容'
...
colN:'内容'
}]
}")]
    public object SplitDataMatrix()
    {
        string split_char = ComFunc.nvlNotrim(PostDataD.split_char);
        string line_char = ComFunc.nvlNotrim(PostDataD.line_char);
        string data_txt = ComFunc.nvlNotrim(PostDataD.data_txt);
        if (data_txt == "")
        {
            return new
            {
                code = "failed",
                msg = "请输入数据"
            };
        }

        if (split_char == "") split_char = ",";
        else split_char = ConvertEscape(split_char);
        if (line_char == "") line_char = "\n";
        else line_char = ConvertEscape(line_char);

        var list = new List<FrameDLRObject>();
        var columns = new List<string>() { "x", "y", "val" };
        var matrix_rows = data_txt.Split(line_char, StringSplitOptions.RemoveEmptyEntries);
        //抓取第一行，资料作为col_2
        var row_1 = matrix_rows.FirstOrDefault().Split(split_char);
        for (var x = 1; x < matrix_rows.Length; x++)
        {
            var row = matrix_rows[x].Split(split_char);
            for (var y = 1; y < row_1.Length; y++)
            {
                FrameDLRObject item = FrameDLRObject.CreateInstance();
                item.SetValue("x", row.First());
                item.SetValue("y", row_1[y]);
                item.SetValue("val", row[y]);

                list.Add(item);
            }
        }
        var transfer_text = new StringBuilder();
        transfer_text.AppendLine(string.Join(split_char, columns));
        foreach (var item in list)
        {
            var arr = new List<string>();
            foreach (var c in columns)
            {
                arr.Add(ComFunc.nvlNotrim(item.GetValue(c)));
            }
            transfer_text.AppendLine(string.Join(split_char, arr));
        }
        return new
        {
            code = "success",
            msg = "",
            columns,
            data = list,
            transfer_text = transfer_text.ToString()
        };
    }
    [EWRARoute("post", "/metadataset/excute/express")]
    [EWRARouteDesc("提供给系统管理员使用，直接执行DBExpress表达式进行系统操作")]
    [EWRAAddInput("express", "string或object或array", "DBExpress表达式", "无默认值", EFFC.Frame.Net.Base.Constants.RestInputPosition.PostData, true)]
    [EWRAOutputDesc("返回结果", @"{
code:'success-成功，failed-失败',
msg:'提示信息',
data:[{
col1:'内容',
col2:'内容'
col3:'内容'
...
colN:'内容'
}]
}")]
    public object ExcuteDBExpress()
    {
        var secretkey = ComFunc.nvl(HeaderData["SystemSecretKey"]);
        if (secretkey == "") secretkey = ComFunc.nvl(HeaderData["systemsecretkey"]);
        if (secretkey == "") secretkey = ComFunc.nvl(HeaderData["Systemsecretkey"]);
        if (secretkey != ComFunc.nvl(MyConfig.GetConfiguration("EFFC", "SystemSecretKey")))
        {
            return new
            {
                code = "failed",
                msg = "系统运维密钥不正确"
            };
        }
        if (PostDataD.express == null)
        {
            return new
            {
                code = "failed",
                msg = "express不可为空"
            };
        }
        var up = DB.NewDBUnitParameter();
        BeginTrans();
        if (!(PostDataD.express is IEnumerable<object>))
        {
            FrameDLRObject exp = null;
            if (PostDataD.express is string)
            {
                var express = ComFunc.nvl(PostDataD.express);
                exp = FrameDLRObject.IsJsonThen(express, null, FrameDLRFlags.SensitiveCase);
            }
            else if (PostDataD.express is FrameDLRObject)
            {
                exp = (FrameDLRObject)PostDataD.express;
            }
            if (exp == null)
            {
                return new
                {
                    code = "failed",
                    msg = "表达式不合法"
                };
            }
            var actiontype = ComFunc.nvl(exp.GetValue("$acttype"));
            try
            {
                if (actiontype.ToLower() == "querybypage")
                {
                    if (ComFunc.nvl(exp.GetValue("$limit")) != "")
                    {
                        up.Count_Of_OnePage = IntStd.IsNotIntThen(exp.GetValue("$limit"), 5);
                        exp.Remove("$limit");
                    }
                    if (ComFunc.nvl(exp.GetValue("$page")) != "")
                    {
                        up.ToPage = IntStd.IsNotIntThen(exp.GetValue("$page"), 1);
                        exp.Remove("$page");
                    }
                }
                var result = DB.Excute(up, exp, true);
                CommitTrans();
                if (actiontype.ToLower() == "query")
                {
                    return new
                    {
                        code = "success",
                        msg = "",
                        data = result.QueryData<FrameDLRObject>()
                    };
                }
                else if (actiontype.ToLower() == "querybypage")
                {
                    return ResultHelper.DFormQueryByPageFormat(result);
                }
                else
                {
                    return new
                    {
                        code = "success",
                        msg = "操作成功"
                    };
                }
            }
            catch (Exception ex)
            {
                RollBack();
                return new
                {
                    code = "success",
                    msg = $"操作失败：{ex.Message}"
                };
            }
        }
        else
        {
            var arr = (IEnumerable<object>)PostDataD.express;
            var exparr = new List<FrameDLRObject>();
            foreach (var item in arr)
            {
                FrameDLRObject exp = null;
                if (item is string)
                {
                    var express = ComFunc.nvl(item);
                    exp = FrameDLRObject.IsJsonThen(express, null, FrameDLRFlags.SensitiveCase);
                }
                else if (item is FrameDLRObject)
                {
                    exp = (FrameDLRObject)item;
                }
                if (exp == null)
                {
                    return new
                    {
                        code = "failed",
                        msg = "表达式不合法"
                    };
                }
                exparr.Add(exp);
            }
            if (exparr.Count <= 0)
            {
                return new
                {
                    code = "failed",
                    msg = "表达式不合法"
                };
            }
            var index = 1;
            UnitDataCollection result = null;
            FrameDLRObject rtndata = FrameDLRObject.CreateInstance(FrameDLRFlags.SensitiveCase);
            foreach (var exp in exparr)
            {
                try
                {
                    var actiontype = ComFunc.nvl(exp.GetValue("$acttype"));
                    if (actiontype.ToLower() == "querybypage")
                    {
                        if (ComFunc.nvl(exp.GetValue("$limit")) != "")
                        {
                            up.Count_Of_OnePage = IntStd.IsNotIntThen(exp.GetValue("$limit"), 5);
                            exp.Remove("$limit");
                        }
                        if (ComFunc.nvl(exp.GetValue("$page")) != "")
                        {
                            up.ToPage = IntStd.IsNotIntThen(exp.GetValue("$page"), 1);
                            exp.Remove("$page");
                        }
                    }
                    result = DB.Excute(up, exp, true);
                    if (actiontype.ToLower() == "query")
                    {
                        rtndata.SetValue($"result_{index}", result.QueryData<FrameDLRObject>());
                    }
                    else if (actiontype.ToLower() == "querybypage")
                    {
                        rtndata.SetValue($"result_{index}", ResultHelper.DFormQueryByPageFormat(result));
                    }
                }
                catch (Exception ex)
                {
                    RollBack();
                    return new
                    {
                        code = "failed",
                        msg = $"第{index}表达式操作失败：{ex.Message}"
                    };
                }
                index++;
            }
            CommitTrans();

            return new
            {
                code = "success",
                msg = "",
                data = rtndata
            };
        }
    }
    /// <summary>
    /// 转义各种特殊符号
    /// </summary>
    /// <param name="str"></param>
    /// <returns></returns>
    private string ConvertEscape(string str)
    {
        var rtn = str;
        var mapchar = new Dictionary<string, string>()
            {
                { "\\r","\r"},
                { "\\n","\n"},
                { "\\t","\t"},
                { "\\f","\f"},
                { "\\v","\v"},
                { "\\a","\a"},
                { "\\'","\'"},
                { "\\\"","\""},
            };
        foreach (var item in mapchar)
        {
            rtn = rtn.Replace(item.Key, item.Value);
        }
        return rtn;
    }
    /// <summary>
    /// 删除上传的文件
    /// </summary>
    /// <param name="file_path">~表示根目录</param>
    /// <returns></returns>
    bool delUploadFile(string file_path)
    {
        return FileHelper.DelUploadFile(file_path);
    }

    private Dictionary<string, dynamic> getTableColumnsMap(UnitParameter metaup)
    {
        var s = from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
                join t2 in DB.LamdaTable(metaup, "EXTEND_METADATA_COLUMNS", "b") on t.metauid equals t2.metauid
                join t3 in DB.LamdaTable(metaup, "EXTEND_METADATA_DATATYPE", "c").LeftJoin() on t2.MetaDataType equals t3.DataType
                where t.iscreated == 1 && t2.IsVirsual == 0
                select new
                {
                    uid = t.metauid,
                    table_name = t.metaname,
                    column_name = t2.metacolumnname,
                    column_desc = t2.metacolumndesc,
                    ui_type = t3.UI_Type
                };

        var list = s.GetQueryList(metaup);
        var dic_list = (from t in DB.LamdaTable(metaup, "EXTEND_DICTIONARY_TABLE", "a")
                        where t.iscreated == 1
                        select new
                        {
                            uid = t.dic_uid,
                            table_name = t.dic_name,
                            is_tree = t.istree
                        }).GetQueryList(metaup);

        foreach (FrameDLRObject item in dic_list)
        {
            var istree = BoolStd.IsNotBoolThen(item.GetValue("is_tree"));
            item.Remove("is_tree");
            var newitem = (FrameDLRObject)item.Clone();
            newitem.SetValue("column_name", "code");
            newitem.SetValue("column_desc", "编号");
            newitem.SetValue("ui_type", "Input");
            list.Add(newitem);
            newitem = (FrameDLRObject)item.Clone();
            newitem.SetValue("column_name", "value");
            newitem.SetValue("column_desc", "值");
            newitem.SetValue("ui_type", "Input");
            list.Add(newitem);
            if (istree)
            {
                newitem = (FrameDLRObject)item.Clone();
                newitem.SetValue("column_name", "level");
                newitem.SetValue("column_desc", "层级");
                newitem.SetValue("ui_type", "Input");
                list.Add(newitem);

                newitem = (FrameDLRObject)item.Clone();
                newitem.SetValue("column_name", "p_code");
                newitem.SetValue("column_desc", "父编号");
                newitem.SetValue("ui_type", "Input");
                list.Add(newitem);
            }
        }

        var rtn = new Dictionary<string, dynamic>();
        foreach (dynamic item in list)
        {
            var key = $"{item.table_name}.{item.column_name}";
            rtn.Add(key.ToLower(), item);
        }
        return rtn;
    }
    /// <summary>
    /// 根据自动填充Method的名称设定，生成对应的值
    /// </summary>
    /// <param name="fix_mathod_name">自动填充Method名称</param>
    /// <param name="length">生成值的长度，Random和Random_Code有效</param>
    /// <returns></returns>
    object genAutoFixValue(string fix_mathod_name, int length = 0)
    {
        switch (fix_mathod_name)
        {
            case "GUID":
                return Guid.NewGuid().ToString();
            case "Random":
                return ComFunc.RandomCode(length);
            case "Random_Code":
                return ComFunc.RandomString(length, true, true, true, false);
            case "Now":
                return DateTime.Now.ToString("yyyy-MM-dd");
            default:
                return fix_mathod_name;
        }
    }
    /// <summary>
    /// 生成自动代码
    /// </summary>
    /// <param name="up">业务DB的UP</param>
    /// <param name="tablename"></param>
    /// <param name="column"></param>
    /// <param name="format"></param>
    /// <returns></returns>
    object genAutoCode(UnitParameter up, string tablename, string column, string format)
    {
        var list = (from t in DB.LamdaTable(up, tablename)
                    select t).Max(column).GetQueryList(up);
        var now = DateTime.Now;
        if (list.Count <= 0)
        {
            return string.Format(format, 1)
                .Replace("yyyy", now.ToString("yyyy"))
                .Replace("MM", now.ToString("MM"))
                .Replace("dd", now.ToString("dd"))
                .Replace("HH", now.ToString("HH"))
                .Replace("mm", now.ToString("mm"))
                .Replace("ss", now.ToString("ss"))
                .Replace("fff", now.ToString("fff"));
        }
        else
        {
            var tmp = string.Format(format, 0)
                .Replace("yyyy", now.ToString("yyyy"))
                .Replace("MM", now.ToString("MM"))
                .Replace("dd", now.ToString("dd"))
                .Replace("HH", now.ToString("HH"))
                .Replace("mm", now.ToString("mm"))
                .Replace("ss", now.ToString("ss"))
                .Replace("fff", now.ToString("fff"));
            var maxvalue = ComFunc.nvl(list.First().Items[0].Value);
            var myear = "";
            var mmonth = "";
            var mday = "";
            var mhour = "";
            var mmin = "";
            var msecond = "";
            var mms = "";

            var index_yyyy = tmp.IndexOf("yyyy");
            var index_MM = tmp.IndexOf("MM");
            var index_dd = tmp.IndexOf("dd");
            var index_HH = tmp.IndexOf("HH");
            var index_mm = tmp.IndexOf("mm");
            var index_ss = tmp.IndexOf("ss");
            var index_fff = tmp.IndexOf("fff");

            //找出maxvalue中的年月日时分秒的值
            if (index_yyyy > -1)
            {
                myear = maxvalue.Substring(index_yyyy, 4);
            }
            if (index_MM > -1)
            {
                mmonth = maxvalue.Substring(index_MM, 2);
            }
            if (index_dd > -1)
            {
                mday = maxvalue.Substring(index_dd, 2);
            }
            if (index_HH > -1)
            {
                mhour = maxvalue.Substring(index_HH, 2);
            }
            if (index_mm > -1)
            {
                mmin = maxvalue.Substring(index_mm, 2);
            }
            if (index_ss > -1)
            {
                msecond = maxvalue.Substring(index_ss, 2);
            }
            if (index_fff > -1)
            {
                mms = maxvalue.Substring(index_fff, 2);
            }
            var tt = maxvalue;
            if (!string.IsNullOrEmpty(myear))
                tt = tt.Replace(myear, "");
            if (!string.IsNullOrEmpty(mmonth))
                tt = tt.Replace(mmonth, "");
            if (!string.IsNullOrEmpty(mday))
                tt = tt.Replace(mday, "");
            if (!string.IsNullOrEmpty(mhour))
                tt = tt.Replace(mhour, "");
            if (!string.IsNullOrEmpty(mmin))
                tt = tt.Replace(mmin, "");
            if (!string.IsNullOrEmpty(msecond))
                tt = tt.Replace(msecond, "");
            if (!string.IsNullOrEmpty(mms))
                tt = tt.Replace(mms, "");

            var new_max = new string(tt.ToArray().Where(w => IntStd.IsNotIntThen(w) != 0).ToArray());

            return IntStd.IsInt(new_max) ? string.Format(format, IntStd.IsNotIntThen(new_max) + 1)
                .Replace("yyyy", now.ToString("yyyy"))
                .Replace("MM", now.ToString("MM"))
                .Replace("dd", now.ToString("dd"))
                .Replace("HH", now.ToString("HH"))
                .Replace("mm", now.ToString("mm"))
                .Replace("ss", now.ToString("ss"))
                .Replace("fff", now.ToString("fff")) :
                string.Format(format, 1)
                .Replace("yyyy", now.ToString("yyyy"))
                .Replace("MM", now.ToString("MM"))
                .Replace("dd", now.ToString("dd"))
                .Replace("HH", now.ToString("HH"))
                .Replace("mm", now.ToString("mm"))
                .Replace("ss", now.ToString("ss"))
                .Replace("fff", now.ToString("fff"));

        }
    }
    object convert2DBValue(object ori_value, string datatype)
    {
        if (ComFunc.nvl(ori_value) == "")
        {
            return DBNull.Value;
        }
        switch (datatype)
        {
            case "time":
                return DateTimeStd.IsDateTimeThen($"1900-01-01 {ori_value}", "yyyy-MM-dd HH:mm:ss");
            case "date":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-MM-dd HH:mm:ss");
            case "datetime":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-MM-dd HH:mm:ss");
            case "date_year":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-01-01 00:00:00", "yyyy", "yyyy-MM-dd");
            case "date_year_month":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-MM-01 00:00:00", "yyyy-M", "yyyy-MM", "yyyy-MM-dd");
            case "multi-file":
                return ComFunc.ToJson(ori_value);
            case "file-base64":
                return ComFunc.ToJson(ori_value, false);
            case "multi-select":
                return ComFunc.ToJson(ori_value);
            case "multi-pop":
                return ComFunc.ToJson(ori_value);
            case "bit":
                return BoolStd.ConvertTo(ori_value, 1, 0);
            case "pictures":
                return ComFunc.ToJson(ori_value);
            case "checkbox":
                return ComFunc.ToJson(ori_value);
            case "multi_cadecase_main":
                return ComFunc.ToJson(ori_value);
            case "multi_cadecase_tree":
                return ComFunc.ToJson(ori_value);
            default:
                return ori_value;
        }
    }
    /// <summary>
    /// 转换成控件的值
    /// </summary>
    /// <param name="ori_value"></param>
    /// <param name="datatype"></param>
    /// <returns></returns>
    object convert2UIValue(object ori_value, string datatype)
    {
        switch (datatype)
        {
            case "time":
                return DateTimeStd.IsDateTimeThen(ori_value, "HH:mm:ss");
            case "date":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-MM-dd");
            case "datetime":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-MM-dd HH:mm:ss");
            case "date_year":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-MM-dd");//给前端都返回标准格式，显示效果由前端处理
            case "date_year_month":
                return DateTimeStd.IsDateTimeThen(ori_value, "yyyy-MM-dd");//给前端都返回标准格式，显示效果由前端处理
            case "multi-file":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "file-base64":
                return FrameDLRObject.IsJsonThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "multi-select":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "multi-pop":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "bit":
                return BoolStd.IsNotBoolThen(ori_value);
            case "pictures":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "checkbox":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "multi_cadecase_main":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            case "multi_cadecase_tree":
                return FrameDLRObject.IsJsonArrayThen(ComFunc.nvl(ori_value), null, FrameDLRFlags.SensitiveCase);
            default:
                return ori_value;
        }
    }
    /// <summary>
    /// 针对主从表构建树结构表
    /// </summary>
    /// <param name="metaup"></param>
    /// <param name="tablename">目标table的名称</param>
    /// <returns>[{
    /// MetaUID:'元数据表UID',
    /// MetaName:'元数据表名',
    /// MetaMainUID:'关联主表UID',
    /// MetaMainShowColumn:'关联主表的显示栏位',
    /// level:'层级'
    /// }]</returns>
    private List<FrameDLRObject> BuildCadecaseMS_MetaTreeInfo(UnitParameter metaup, string tablename)
    {
        var tablelist = (from t in DB.LamdaTable(metaup, "EXTEND_METADATA", "a")
                         select new
                         {
                             t.MetaUID,
                             t.MetaName,
                             t.MetaMainUID,
                             t.MetaMainShowColumn
                         }).GetQueryList(metaup);
        //建立树状结构
        var tree_tables = new List<FrameDLRObject>();
        Action<string, int> tree_build = null;
        tree_build = delegate (string p, int level)
        {
            var l = tablelist.Where(w => ComFunc.nvl(w.MetaMainUID) == p).ToList();
            if (l.Count <= 0) return;
            foreach (dynamic item in l)
            {
                item.level = level + 1;
                //递归调用
                string pk = ComFunc.nvl(item.MetaUID);
                tree_build(pk, item.level);
            }
        };
        tree_build.Invoke("", 0);
        //根据层级找出当前要抓取的表
        var lasttableinfo = tablelist.Where(w => ComFunc.nvl(w.MetaName) == tablename).FirstOrDefault();
        if (lasttableinfo == null) return new List<FrameDLRObject>();

        var needed_tree_tables = new List<FrameDLRObject>();
        needed_tree_tables.Add(lasttableinfo);
        Action<string> needed_table_build = null;
        needed_table_build = delegate (string p_uid)
        {
            var l = tablelist.Where(w => ComFunc.nvl(w.MetaUID) == p_uid).FirstOrDefault();
            if (l == null) return;
            needed_tree_tables.Add(l);
            needed_table_build.Invoke(ComFunc.nvl(l.GetValue("MetaMainUID")));
        };
        needed_table_build(ComFunc.nvl(lasttableinfo.GetValue("MetaMainUID")));

        return needed_tree_tables;
    }
}
}
